﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;

namespace IntelligentDecisioning.SharePoint
{
    //TODO: Remove hardcoded field names
    //TODO: Add Logging Framework - Add a hidden list to log to
    //TODO: Use our list provisioning code rather than provisioning a list directly!

    /// <summary>
    /// We use our base create a "FeatureFramework" which can be used
    /// by all the ID sharepoint feature that we create. This framework consists of two
    /// hidden lists which are created at Site collection level. These lists are used
    /// by specifc features to register the featues prescence and configutation requirements.
    /// We can then create a generic configuration page and ECB menu item for each feature registered.
    /// </summary>
    internal class SharePointConfiguration
    {
        #region Constants

        /// <summary>
        /// A list containing all theID features currently activated in a site collection
        /// </summary>
        internal const String FEATURE_DEFINITION_LIST = "id-sharepoint_FeatureDefinitionList";
        
        /// <summary>
        /// A list that contains the current configuration information for each active feature
        /// </summary>
        internal const String FEATURE_CONFIGURATION_LIST = "id-sharepoint_FeatureConfigurationList";

        /// <summary>
        /// A list that is used to log the insallation of a particular feature
        /// </summary>
        internal const string FEATURE_INSTALLATION_LOG = "id-sharepoint_FeatureInstallationLog";

        #endregion

        #region Provision the Feature Framework

        /// <summary>
        /// Creates the Feature configuration Framework for a given site collection
        /// </summary>
        /// <param name="site">The site collection</param>
        internal static void AddFeatureConfigurationFramework(SPSite site)
        {
            if (site == null) throw new ArgumentNullException("Site");

            if(FeatureConfigurationFrameWorkExists(site) == false)
            {
                AddFeatureInstallationLog(site);
                AddFeatureDefinitionList(site);
                AddFeatureConfigurationList(site);
                AddFeatureEventHandlers(site);
                site.RootWeb.Update();
            }
        }

        private static void AddFeatureInstallationLog(SPSite site)
        {
            Guid listId = site.RootWeb.Lists.Add(FEATURE_INSTALLATION_LOG, "Creates an installation log for each feature", SPListTemplateType.GenericList);
            SPList configurationList = site.RootWeb.Lists[listId];
            // configurationList.Fields.Add("Name", SPFieldType.Text, true); - use title
            String s = configurationList.Fields.Add("Category", SPFieldType.Text, false);
            configurationList.Fields.Add("Message", SPFieldType.Text, true);
            configurationList.Fields.Add("FeatureId", SPFieldType.Guid, true); // foreign key to feature definition list
            configurationList.Update();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="site"></param>
        private static void AddFeatureEventHandlers(SPSite site)
        {
            //was going to automatically detect our feature activation
            // This is not currently possible!
            // We must rely on the ID features "behaving themselves" and registering explicitly
        }

        /// <summary>
        /// Provisions the feature configuration list to the specified site collection
        /// </summary>
        /// <param name="site">The site collection</param>
        private static void AddFeatureConfigurationList(SPSite site)
        {
            Guid listId = site.RootWeb.Lists.Add(FEATURE_CONFIGURATION_LIST, "Stores configuration data for Intelligent Decisioning features", SPListTemplateType.GenericList);
            SPList configurationList = site.RootWeb.Lists[listId];
           // configurationList.Fields.Add("Name", SPFieldType.Text, true); - use title
            configurationList.Fields.Add("Value", SPFieldType.Text, false);
            configurationList.Fields.Add("Type", SPFieldType.Text, true);
            configurationList.Fields.Add("FeatureId", SPFieldType.Guid, true); // foreign key to feature definition list
            configurationList.Update();
        }

        /// <summary>
        /// Provisions the feature definition list to the specified site collection
        /// </summary>
        /// <param name="site">the site collection</param>
        private static void AddFeatureDefinitionList(SPSite site)
        {
            Guid listId = site.RootWeb.Lists.Add(FEATURE_DEFINITION_LIST, "Stores configuration data for Intelligent Decisioning features", SPListTemplateType.GenericList);
            SPList definitionList = site.RootWeb.Lists[listId];
            definitionList.Fields.Add("FeatureId", SPFieldType.Guid, true);
            // Used to store an xml documnet with configartion information
            definitionList.Fields.Add("ConfigurationMetaData", SPFieldType.Note, true);
            definitionList.Update();
        }

        #endregion

        #region Remove the Feature Framework

        /// <summary>
        /// Calling ths method will break all our installed features - must only be 
        /// called form the base feature uninstall !
        /// </summary>
        /// <param name="site"></param>
        internal static void RemoveFeatureConfigurationFramework(SPSite site)
        {
            if (site == null) throw new ArgumentNullException("Site");

            if (FeatureConfigurationFrameWorkExists(site) == true)
            {
                RemoveEventHandlers(site);
                RemoveFeatureConfigurationList(site);
                RemoveFeatureDefinitionList(site);
                RemoveFeatureInstallationLog(site);
                site.RootWeb.Update();
            }
        }

        private static void RemoveFeatureInstallationLog(SPSite site)
        {
            site.RootWeb.Lists[FEATURE_INSTALLATION_LOG].Delete();
        }

        private static void RemoveFeatureDefinitionList(SPSite site)
        {
            site.RootWeb.Lists[FEATURE_DEFINITION_LIST].Delete();
        }

        private static void RemoveFeatureConfigurationList(SPSite site)
        {
            site.RootWeb.Lists[FEATURE_CONFIGURATION_LIST].Delete();
        }

        private static void RemoveEventHandlers(SPSite site)
        {
            //TODO
        }

        /// <summary>
        /// Checks if our feature configuration framework has already been defined
        /// on this site collection
        /// </summary>
        /// <param name="site"></param>
        /// <returns></returns>
        static bool FeatureConfigurationFrameWorkExists(SPSite site)
        {
            bool frameworkInstalled = false;

            foreach (SPList list in site.RootWeb.Lists)
            {
                if (list.Title == FEATURE_DEFINITION_LIST)
                {
                    frameworkInstalled = true;
                    break;
                }
            }

            return frameworkInstalled;
        }

        #endregion

        #region TODO !

        #region Register Feature

        #endregion

        #region Register Feature Configuration

        #endregion

        #region Get Feature Configuration

        #endregion


        #region Update Feature Configuration

        #endregion


        #region DeRegister Feature

        #endregion

        #endregion
    }
}
